#ifndef _COMMON_H
#define _COMMON_H
#include <assert.h>

#include <time.h>
#include <sys/time.h>    //gettimeofday 
#include <sys/stat.h>    //定义在打开和创建文件时用到的一些符号常量
#include <unistd.h>      // linux  read  write
#include <string.h>
#include <stdio.h>       // linux input output 
#include <stdlib.h>      //standard library 
#include <stdint.h>
#include <signal.h>      
#include <math.h>
#include <malloc.h>
#include <fcntl.h>       //定义 open,fcntl函数原型
#include <error.h>  

#include <sys/types.h>    //off_t
#include <sys/socket.h>   //socket ,blind ,listen ,accept,...
#include <netinet/in.h>   //sockaddr_in ,struct sockaddr,...
#include <arpa/inet.h>    //inet_addr ,inet_ntoa ,htonl,...
#include <net/if.h>       // struct ifreq ,struct ifconf
#include <sys/ioctl.h>    //setsockopt
#include <pthread.h>      //pthread_create
#include <netinet/tcp.h>  //
#include <sys/resource.h> 


#define K 4 //数据分块个数
#define R 2 //校验分块个数
#define W 8 //编码字长
#define NodeNumTotal 13//节点总个数
#define RackNumTotal 6//机架总数 需要满足条件:K+R<=RackNumTotal
#define ClientNum 1//client的个数
#define Block_Size 4*1024 //数据分块大小为4KB
#define Sort_Way 1//0-空间局部性 1-时间局部性 
#define Eviction_Proption 20
#define Archival_Time 80000
#define IsBegin_Archival_Process 0

#define Max_Wait 32  //socke最大连接等待时间
#define Max_Length_backlog  10 //socket可排队的最大连接个数
#define SOCKMAX (1024*1024)   //socket 最大限制
#define Max_Trace 100001

#define CONFIG_NODE "config_node" //节点配置文件名
#define CONFIG_RACK "config_rack" //机架配置文件名
#define TRACE "trace.txt"//trace文件名
#define IPLen 16//节点ip的长度
#define ERR -1    //错误标记
#define COMMENTS '#'
#define ETH "eth"

#define Worker2MasterPort  41000//Worker与Master之间通信使用的端口
#define Worker2WorkerPort  42000//Worker之间通信使用的端口
#define Client2WorkerPort  43000//Client与Worker之间通信使用的端口
#define Master2WorkerPort  44000//Master与Worker之间通信使用的端口
#define Client2MasterPort  45000
#define Worker2GateWayPort 46000
#define GateWay2WorkerPort 47000

typedef struct Node
{
	int nodeID;//节点ID
	int rackID;//所属机架ID
	char ip[IPLen];//节点Ip地址
}Node;

typedef struct Rack
{
	int rackID;//机架ID
	int nodeNum;//机架上节点个数
	int* nodeIDs;//机架上各节点ID
}Rack;

typedef struct Block
{
	long long blockID;
	char dataBuf[Block_Size];
}Block;

typedef struct BlockMeta
{
	long long blockID;//数据块ID
	int nodeID;//所属节点ID
	int rackID;//所属节点所在机架ID
	char flag;//'p'主副本,'s'从副本,'u'组成条带等待编码,'e'编码完毕
	long NOA;//访问量
	int isParity;//是否是校验块 0:不是 1:是
	long RG_ID;//数据块所属冗余组的ID
	int RG_Position;//数据块在冗余组的位置
	long timestamp;//数据块创建或修改的时间戳
}BlockMeta;

//冗余组信息 不充分需要修改
typedef struct Redundancy_Group
{
	long RG_ID;
	long long blockIDs[K];
	long long parityIDs[R];
	int isFinish;
	int primaryRackID;
}RGroup;

typedef struct Client2WorkerRequest
{
	long requestID;
	long long blockID;
	int nodeID;
	int flag;//'1'=set '0'=get
	int isPrimary;
}Client2WorkerRequest;

typedef struct Worker2WorkerRequest
{
	long requestID;
	long long blockID;
	int fromNodeID;
	int toNodeID;
	int flag;//2=del 1=set 0=get
}Worker2WorkerRequest;

typedef struct ArchivalRequest
{
	long RG_ID;
	long long blockIDs[K];
	long long parityIDs[R];
	int originalNodeIDs[K];
	int parityNodeIDs[R];
}ArchivalRequest;

typedef struct Client2MasterRequest{
	long requestID;
	int flag; //0=get 1=set 
	long long blockID;
}Client2MasterRequest;


typedef struct Worker2MasterRequest
{
	long requestID;
	int isPrimary;
	long long blockID;
	int nodeID;
	int flag;
}Worker2MasterRequest;

typedef struct Master2ClientResponse4Read
{
	long responseID;
	int nodeID1;
}Master2ClientResponse4Read;

typedef struct Master2ClientResponse4Write
{
	long responseID;
	int nodeID1;
	int nodeID2;
}Master2ClientResponse4Write;


int randn(int range);//随机生成一个【0，range)的整数
char* lltoa(long long num);
char* ltoa(long num);

Node* read_config_Node(const char *fname);//读取节点配置文件
Rack* read_config_Rack(const char *fname);//读取机架配置文件

void get_ipaddr(char *ip,int len);//获取本机的IP地址
int set_server_limit(void);//设置最大文件描述符
int current_node(Node * nodes);//获取当前节点的编号

int connect_try(char *ip,ushort port);//尝试连接目标server，返回connectfd或者-1
int server_accept(ushort port,int backlog);//服务器端bind listen以及accept

ssize_t read_bytes(int fd,char *buf,size_t nbytes);    //一次读文件
ssize_t write_bytes(int fd,char *buf,size_t nbytes);   //一次写文件
ssize_t send_bytes(int sockfd,char *buf,size_t nbytes);//一次性发送
ssize_t recv_bytes(int sockfd,char *buf,size_t nbytes);//一次性接收
void calc_xor(char *d1,char * d2,char *out,size_t len);
#endif


